﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Vector = System.Windows.Vector;

namespace SharpSoft.WPF.Controls
{
    /// <summary>
    /// 颜色拾取器
    /// </summary>
    public class ColorPicker : Control
    {
        static ColorPicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
        }
        public ColorPicker()
        {
            this.PresetColors = new System.Collections.ObjectModel.ObservableCollection<Color>();
            this.Loaded += ColorPicker_Loaded;
            this.Unloaded += ColorPicker_Unloaded;
            this.AddHandler(ButtonBase.ClickEvent, new System.Windows.RoutedEventHandler(PresetColor_ButtonClick));

            processPresetColors();
        }

        private void ButtonBase_Click(object sender, RoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void ColorPicker_Loaded(object sender, RoutedEventArgs e)
        {
            this.UpdateColor();//初始化时设置滑块位置
        }
        private void ColorPicker_Unloaded(object sender, RoutedEventArgs e)
        {
            LastPickColor = this.Color;
            if (RecentColors.Count >= RecentColorsRemberCount)
            {
                RecentColors.RemoveAt(0);
            }
            var c = this.Color;
            c.A = 255;
            if (RecentColors.Contains(c))
            {
                RecentColors.Remove(c);
            }
            RecentColors.Add(c);
        }




        #region Thumbs
        private void Slider_A_DragChange(object sender, EventArgs e)
        {
            reCalcAlpha();
        }

        private void Slider_B_DragChange(object sender, EventArgs e)
        {
            var c = this.ColorWithoutAlpha;
            c.B = Convert.ToByte(slider_B.X * 255);
            this.ColorWithoutAlpha = c;
            SetColorWithoutAlpha(c);
        }

        private void Slider_G_DragChange(object sender, EventArgs e)
        {
            var c = this.ColorWithoutAlpha;
            c.G = Convert.ToByte(slider_G.X * 255);
            this.ColorWithoutAlpha = c;
            SetColorWithoutAlpha(c);
        }

        private void Slider_R_DragChange(object sender, EventArgs e)
        {
            var c = this.ColorWithoutAlpha;
            c.R = Convert.ToByte(slider_R.X * 255);
            this.ColorWithoutAlpha = c;
            SetColorWithoutAlpha(c);
        }

        private void Slider_SV_DragChange(object sender, EventArgs e)
        {
            reCalcColor2();
        }

        private void Slider_H_DragChange(object sender, EventArgs e)
        {
            reCalcColor1();
        }


        SliderBlock slider_H, slider_SV, slider_A, slider_R, slider_G, slider_B;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            slider_H = (SliderBlock)this.Template.FindName("slider_H", this);
            slider_SV = (SliderBlock)this.Template.FindName("slider_SV", this);
            slider_A = (SliderBlock)this.Template.FindName("slider_A", this);

            slider_R = (SliderBlock)this.Template.FindName("slider_R", this);
            slider_G = (SliderBlock)this.Template.FindName("slider_G", this);
            slider_B = (SliderBlock)this.Template.FindName("slider_B", this);


            slider_H.DragChange += Slider_H_DragChange;
            slider_SV.DragChange += Slider_SV_DragChange;

            slider_R.DragChange += Slider_R_DragChange;
            slider_G.DragChange += Slider_G_DragChange;
            slider_B.DragChange += Slider_B_DragChange;

            slider_A.DragChange += Slider_A_DragChange;
        }
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == ColorWithoutAlphaProperty)
            {
                this.reCalcAlpha();
                reCalcRGBSlider();
            }
            else if (e.Property == Color1Property)
            {
                this.reCalcColor2();
            }
            else if (e.Property == AllowAlphaProperty)
            {
                var c = this.Color;
                if (!this.AllowAlpha)
                {
                    c.A = 255;
                    this.SetValue(ColorProperty, c);
                }
                else
                {
                    if (slider_A != null)
                    {
                        c.A = Convert.ToByte(slider_A.X * 255);
                    }
                    this.SetValue(ColorProperty, c);
                }
            }
            else if (e.Property == ColorProperty)
            {
                this.ColorBrush = new SolidColorBrush(this.Color);
            }
        }

        #endregion

        #region tranColors

        private void reCalcRGBSlider()
        {
            if (slider_R == null || slider_G == null || slider_B == null)
            {
                return;
            }
            var c = ColorWithoutAlpha;
            #region 重新计算RGB滑块的背景色 
            LinearGradientBrush lgb = new LinearGradientBrush();
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(0, c.G, c.B), 0));
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(255, c.G, c.B), 1));
            slider_R.Background = lgb;

            lgb = new LinearGradientBrush();
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(c.R, 0, c.B), 0));
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(c.R, 255, c.B), 1));
            slider_G.Background = lgb;

            lgb = new LinearGradientBrush();
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(c.R, c.G, 0), 0));
            lgb.GradientStops.Add(new GradientStop(Color.FromRgb(c.R, c.G, 255), 1));
            slider_B.Background = lgb;
            #endregion

            #region 重新计算RGB滑块的位置

            var rgb = ColourToRGB(c);
            slider_R.X = rgb.R;
            slider_G.X = rgb.G;
            slider_B.X = rgb.B;
            #endregion
        }

        /// <summary>
        /// 重新计算颜色1
        /// </summary>
        private void reCalcColor1()
        {
            var h = GetH();
            var hsv = new HSV(h, 1, 1);
            this.Color1 = RGBToColour(hsv.ToRGB());
        }
        /// <summary>
        /// 重新计算颜色2
        /// </summary>
        private void reCalcColor2()
        {
            var hsv = getHSV();
            this.ColorWithoutAlpha = RGBToColour(hsv.ToRGB());
        }
        /// <summary>
        /// 重计算透明度
        /// </summary>
        private void reCalcAlpha()
        {
            if (slider_A == null)
            {
                return;
            }
            var c2 = this.ColorWithoutAlpha;
            if (this.AllowAlpha)
            {//允许透明度
                c2.A = Convert.ToByte(slider_A.X * 255);
            }

            this.SetValue(ColorProperty, c2);//不触发setColor
        }
        /// <summary>
        /// 设置当前透明度
        /// </summary>
        /// <param name="a"></param>
        private void SetAlpha(float a)
        {
            clamp(ref a, 1f, 0f);
            if (slider_A != null)
            {
                slider_A.X = a;
            }

        }

        /// <summary>
        /// 根据滑块1位置获取H分量
        /// </summary>
        /// <returns></returns>
        private float GetH()
        {
            var h = Convert.ToSingle(360 * slider_H.Y);
            clamp(ref h, 360f, 0f);
            return h;
        }

        /// <summary>
        /// 根据滑块的位置获取hsv
        /// </summary>
        /// <returns></returns>
        private HSV getHSV()
        {
            var h = GetH();

            var v = Convert.ToSingle(1d - slider_SV.Y);
            var s = Convert.ToSingle(slider_SV.X);
            clamp(ref v, 1f, 0f);
            clamp(ref s, 1f, 0f);
            return new HSV(h, s, v);
        }
        /// <summary>
        /// 设置HSV，将滑块放置到指定位置。
        /// </summary>
        /// <param name="hsv"></param>
        private void setHSV(HSV hsv)
        {
            if (slider_H == null || slider_SV == null)
            {
                return;
            }

            var y1 = hsv.H / 360f;
            clamp(ref y1, 1f, 0f);
            var x2 = hsv.S;
            var y2 = 1f - hsv.V;
            clamp(ref x2, 1f, 0f);
            clamp(ref y2, 1f, 0f);


            slider_H.Y = y1;
            reCalcColor1();

            slider_SV.Y = y2;
            slider_SV.X = x2;
            reCalcColor2();
        }

        /// <summary>
        /// 设置当前颜色
        /// </summary>
        /// <param name="color"></param>
        private void SetColor(Color color)
        {
            SetAlpha(color.A / 255f);
            SetColorWithoutAlpha(color);
        }
        /// <summary>
        /// 设置颜色但是忽略它的透明度
        /// </summary>
        /// <param name="color"></param>
        private void SetColorWithoutAlpha(Color color)
        {
            var rgb = ColourToRGB(color);
            var hsv = rgb.ToHSV();
            setHSV(hsv);
            color.A = 255;
            this.ColorWithoutAlpha = color;
            reCalcAlpha();
        }
        /// <summary>
        /// 更新当前颜色,调用后强制将当前的滑块位置调整到当前颜色的设置位置
        /// </summary>
        public void UpdateColor()
        {
            this.SetColor(this.Color);
        }


        /// <summary>
        /// 约束值，将值约束在指定的范围内
        /// </summary>
        /// <param name="value"></param>
        /// <param name="max"></param>
        /// <param name="min"></param>
        private static void clamp(ref float value, float max = 1f, float min = 0f)
        {
            if (value > max) value = max;
            if (value < min) value = min;
        }
        /// <summary>
        /// RGB转为WPF的Color
        /// </summary>
        /// <param name="rgb"></param>
        /// <returns></returns>
        private static Color RGBToColour(RGB rgb)
        {
            var r = rgb.R;
            var g = rgb.G;
            var b = rgb.B;
            clamp(ref r, 1f, 0f);
            clamp(ref g, 1f, 0f);
            clamp(ref b, 1f, 0f);
            return Color.FromRgb(Convert.ToByte(r * 255), Convert.ToByte(g * 255), Convert.ToByte(b * 255));
        }
        /// <summary>
        /// WPF颜色转换为RGB
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        private static RGB ColourToRGB(Color color)
        {
            var r = Convert.ToSingle(color.R / 255F);
            var g = Convert.ToSingle(color.G / 255F);
            var b = Convert.ToSingle(color.B / 255F);
            clamp(ref r, 1f, 0f);
            clamp(ref g, 1f, 0f);
            clamp(ref b, 1f, 0f);
            return new RGB(r, g, b);
        }

        #endregion

        #region 属性

        /// <summary>
        /// 主颜色
        /// </summary>
        public Color Color1
        {
            get { return (Color)GetValue(Color1Property); }
            private set { SetValue(Color1PropertyKey, value); }
        }
        private static DependencyPropertyKey Color1PropertyKey = DependencyProperty.RegisterReadOnly("Color1", typeof(Color), typeof(ColorPicker), new PropertyMetadata(default(Color)));
        public static DependencyProperty Color1Property = Color1PropertyKey.DependencyProperty;

        /// <summary>
        /// 不考虑透明通道的结果颜色
        /// </summary>
        public Color ColorWithoutAlpha
        {
            get { return (Color)GetValue(ColorWithoutAlphaProperty); }
            private set { SetValue(ColorWithoutAlphaPropertyKey, value); }
        }
        private static DependencyPropertyKey ColorWithoutAlphaPropertyKey = DependencyProperty.RegisterReadOnly("ColorWithoutAlpha", typeof(Color), typeof(ColorPicker), new PropertyMetadata(default(Color)));
        public static DependencyProperty ColorWithoutAlphaProperty = ColorWithoutAlphaPropertyKey.DependencyProperty;


        /// <summary>
        /// 结果颜色
        /// </summary>
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set
            {
                SetValue(ColorProperty, value);
                SetColor(value);
            }
        }

        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker), new PropertyMetadata(Colors.White));
        /// <summary>
        /// 颜色画刷
        /// </summary>
        public SolidColorBrush ColorBrush
        {
            get { return (SolidColorBrush)GetValue(ColorBrushProperty); }
            private set { SetValue(ColorBrushPropertyKey, value); }
        }
        private static DependencyPropertyKey ColorBrushPropertyKey = DependencyProperty.RegisterReadOnly("ColorBrush", typeof(SolidColorBrush), typeof(ColorPicker), new PropertyMetadata(default(SolidColorBrush)));
        public static DependencyProperty ColorBrushProperty = ColorBrushPropertyKey.DependencyProperty;


        /// <summary>
        /// 是否允许透明通道
        /// </summary>
        public bool AllowAlpha
        {
            get { return (bool)GetValue(AllowAlphaProperty); }
            set { SetValue(AllowAlphaProperty, value); }
        }

        public static readonly DependencyProperty AllowAlphaProperty =
            DependencyProperty.Register("AllowAlpha", typeof(bool), typeof(ColorPicker), new PropertyMetadata(true));
        /// <summary>
        /// 是否显示通过RGB调整颜色的滑块
        /// </summary>
        public bool ShowRGB
        {
            get { return (bool)GetValue(ShowRGBProperty); }
            set { SetValue(ShowRGBProperty, value); }
        }

        public static readonly DependencyProperty ShowRGBProperty =
            DependencyProperty.Register("ShowRGB", typeof(bool), typeof(ColorPicker), new PropertyMetadata(true));

        /// <summary>
        /// 是否显示预设颜色
        /// </summary>
        public bool ShowPresetColors
        {
            get { return (bool)GetValue(ShowPresetColorsProperty); }
            set { SetValue(ShowPresetColorsProperty, value); }
        }

        public static readonly DependencyProperty ShowPresetColorsProperty =
            DependencyProperty.Register("ShowPresetColors", typeof(bool), typeof(ColorPicker), new PropertyMetadata(true));
        /// <summary>
        /// 显示最近使用过的颜色
        /// </summary>
        public bool ShowRecentColors
        {
            get { return (bool)GetValue(ShowRecentColorsProperty); }
            set { SetValue(ShowRecentColorsProperty, value); }
        }

        public static readonly DependencyProperty ShowRecentColorsProperty =
            DependencyProperty.Register("ShowRecentColors", typeof(bool), typeof(ColorPicker), new PropertyMetadata(true));



        #endregion

        #region 预设颜色
        private readonly string[] _presetColors = new string[]
        {
            "#fff",
            "#9e9e9e",
            "#000",

            "#f44336",
            "#e91e63",
            "#9c27b0",
            "#673ab7",
            "#3f51b5",
            "#2196f3",
            "#03a9f4",
            "#00bcd4",
            "#009688",

            "#4caf50",
            "#8bc34a",
            "#cddc39",
            "#ffeb3b",
            "#ffc107",
            "#ff9800",
            "#ff5722",
            "#795548"
        };

        /// <summary>
        /// 预设颜色
        /// </summary>
        public System.Collections.ObjectModel.ObservableCollection<Color> PresetColors
        {
            get { return (System.Collections.ObjectModel.ObservableCollection<Color>)GetValue(PresetColorsProperty); }
            private set { SetValue(PresetColorsPropertyKey, value); }
        }
        private static DependencyPropertyKey PresetColorsPropertyKey = DependencyProperty.RegisterReadOnly("PresetColors", typeof(System.Collections.ObjectModel.ObservableCollection<Color>), typeof(ColorPicker), new PropertyMetadata(default(System.Collections.ObjectModel.ObservableCollection<Color>)));
        public static DependencyProperty PresetColorsProperty = PresetColorsPropertyKey.DependencyProperty;

        /// <summary>
        /// 处理预设颜色
        /// </summary>
        private void processPresetColors()
        {
            foreach (var cstr in _presetColors)
            {
                var color = (Color)ColorConverter.ConvertFromString(cstr);
                PresetColors.Add(color);
            }
        }

        private void PresetColor_ButtonClick(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is ButtonBase btn && btn.Tag is Color color)
            {
                this.Color = (color);
            }
        }
        /// <summary>
        /// 上次拾取的颜色
        /// </summary>
        public static Color LastPickColor { get; set; } = Colors.Black;

        #endregion

        #region 最近颜色
        /// <summary>
        /// 最近使用过的颜色
        /// </summary>
        public static System.Collections.ObjectModel.ObservableCollection<Color> RecentColors { get; set; } = new System.Collections.ObjectModel.ObservableCollection<Color>();

        /// <summary>
        /// 记录近期使用的颜色最大数量
        /// </summary>
        public static int RecentColorsRemberCount { get; set; } = 20;



        #endregion


        #region 颜色结构

        private struct HSV
        {
            public HSV()
            {
                this.H = this.S = this.V = 0f;
            }
            public HSV(float h, float s, float v)
            {
                this.H = h;
                this.S = s;
                this.V = v;
            }


            /// <summary>
            /// 0-360
            /// </summary>
            public float H { get; set; }
            /// <summary>
            /// 0-1
            /// </summary>
            public float S { get; set; }
            /// <summary>
            /// 0-1
            /// </summary>
            public float V { get; set; }

            public RGB ToRGB()
            {
                float h = this.H;
                while (h < 0f) { h += 360f; };
                while (h >= 360f) { h -= 360f; };
                float R, G, B;
                if (V <= 0f)
                { R = G = B = 0f; }
                else if (S <= 0f)
                {
                    R = G = B = V;
                }
                else
                {
                    float hf = h / 60.0f;
                    int i = (int)Math.Floor(hf);
                    float f = hf - i;
                    float pv = V * (1f - S);
                    float qv = V * (1f - S * f);
                    float tv = V * (1f - S * (1f - f));
                    switch (i)
                    {

                        // Red is the dominant color

                        case 0:
                            R = V;
                            G = tv;
                            B = pv;
                            break;

                        // Green is the dominant color

                        case 1:
                            R = qv;
                            G = V;
                            B = pv;
                            break;
                        case 2:
                            R = pv;
                            G = V;
                            B = tv;
                            break;

                        // Blue is the dominant color

                        case 3:
                            R = pv;
                            G = qv;
                            B = V;
                            break;
                        case 4:
                            R = tv;
                            G = pv;
                            B = V;
                            break;

                        // Red is the dominant color

                        case 5:
                            R = V;
                            G = pv;
                            B = qv;
                            break;

                        // Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here.

                        case 6:
                            R = V;
                            G = tv;
                            B = pv;
                            break;
                        case -1:
                            R = V;
                            G = pv;
                            B = qv;
                            break;

                        // The color is not defined, we should throw an error.

                        default:
                            //LFATAL("i Value error in Pixel conversion, Value is %d", i);
                            R = G = B = V; // Just pretend its black/white
                            break;
                    }
                }

                return new RGB(R, G, B);
            }
        }

        private struct RGB
        {
            public RGB()
            {
                this.R = this.G = this.B = 0f;
            }
            public RGB(float r, float g, float b)
            {
                this.R = r;
                this.G = g;
                this.B = b;
            }
            /// <summary>
            /// 0-1
            /// </summary>
            public float R { get; set; }
            /// <summary>
            /// 0-1
            /// </summary>
            public float G { get; set; }
            /// <summary>
            /// 0-1
            /// </summary>
            public float B { get; set; }

            public HSV ToHSV()
            {
                float max = MathF.Max(MathF.Max(R, G), B);
                float min = MathF.Min(MathF.Min(R, G), B);

                float V = max;
                float S = (max - min) / max;
                float H = 0f;
                if (max == min)
                {
                    S = 0;
                }
                else
                {
                    if (max == R)
                    {
                        H = (60 * (G - B) / (max - min));
                    }
                    else if (max == G)
                    {
                        H = (60 * (2 + (B - R) / (max - min)));
                    }
                    else if (max == B)
                    {
                        H = (60 * (4 + (R - G) / (max - min)));
                    }
                }
                if (H < 0) H += 360;


                return new HSV(H, S, V);
            }
        }
        #endregion
    }

    #region 滑块控件
    /// <summary>
    /// 滑块
    /// </summary>
    [TemplatePart(Name = "CANVAS", Type = typeof(Canvas))]
    [TemplatePart(Name = "THUMB", Type = typeof(ContentPresenter))]
    public class SliderBlock : Control
    {
        static SliderBlock()
        {

            DefaultStyleKeyProperty.OverrideMetadata(typeof(SliderBlock), new FrameworkPropertyMetadata(typeof(SliderBlock)));
        }
        public SliderBlock()
        {
            this.Loaded += SliderBlock_Loaded;
            this.Unloaded += SliderBlock_Unloaded;
        }
        #region 鼠标事件

        private void SliderBlock_Unloaded(object sender, RoutedEventArgs e)
        {
        }

        private void SliderBlock_Loaded(object sender, RoutedEventArgs e)
        {
            resetPosition();

        }

        private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            canvas.ReleaseMouseCapture();
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                var p = e.GetPosition(canvas);
                if ((this.Orientation & SliderBlockOrientation.X) == SliderBlockOrientation.X)
                {
                    var w = canvas.ActualWidth;
                    var x = p.X / w;
                    this.X = Math.Min(1d, Math.Max(0d, x));
                }
                if ((this.Orientation & SliderBlockOrientation.Y) == SliderBlockOrientation.Y)
                {
                    var h = canvas.ActualHeight;
                    var y = p.Y / h;
                    this.Y = Math.Min(1d, Math.Max(0d, y));
                }
                this.OnDragChange();
            }
        }

        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var p = e.GetPosition(canvas);
            if ((this.Orientation & SliderBlockOrientation.X) == SliderBlockOrientation.X)
            {
                var w = canvas.ActualWidth;
                var x = p.X / w;
                this.X = Math.Min(1d, Math.Max(0d, x));
            }
            if ((this.Orientation & SliderBlockOrientation.Y) == SliderBlockOrientation.Y)
            {
                var h = canvas.ActualHeight;
                var y = p.Y / h;
                this.Y = Math.Min(1d, Math.Max(0d, y));
            }
            this.OnDragChange();
            canvas.CaptureMouse();
        }
        #endregion

        Canvas canvas;
        ContentPresenter contentPresenter;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            canvas = (Canvas)this.Template.FindName("CANVAS", this);
            contentPresenter = (ContentPresenter)this.Template.FindName("THUMB", this);

            canvas.PreviewMouseLeftButtonDown += Canvas_MouseLeftButtonDown;
            canvas.PreviewMouseMove += Canvas_MouseMove;
            canvas.PreviewMouseLeftButtonUp += Canvas_MouseLeftButtonUp;
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == XProperty)
            {
                resetPosition();
            }
            else if (e.Property == YProperty)
            {
                resetPosition();
            }
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            var t = this.Thumb;
            if (t != null)
            {
                if (double.IsNaN(t.Width) && double.IsNaN(t.Height))
                {
                    if ((this.Orientation & SliderBlockOrientation.X) != SliderBlockOrientation.X)
                    {//垂直
                        t.Width = t.Height = this.ActualWidth;
                    }
                    else if ((this.Orientation & SliderBlockOrientation.Y) != SliderBlockOrientation.Y)
                    {//水平
                        t.Width = t.Height = this.ActualHeight;
                    }
                    else
                    {
                        t.Width = t.Height = this.ActualWidth / 28;
                    }

                }
                resetPosition();
            }
        }

        private void resetPosition()
        {
            if (canvas != null && contentPresenter != null)
            {
                if ((this.Orientation & SliderBlockOrientation.X) != SliderBlockOrientation.X)
                {
                    this.X = 0.5d;
                }
                var w = canvas.ActualWidth;
                Canvas.SetLeft(contentPresenter, this.X * w - contentPresenter.ActualWidth / 2);
                if ((this.Orientation & SliderBlockOrientation.Y) != SliderBlockOrientation.Y)
                {
                    this.Y = 0.5d;
                }
                var h = canvas.ActualHeight;
                Canvas.SetTop(contentPresenter, this.Y * h - contentPresenter.ActualHeight / 2);
            }
        }

        /// <summary>
        /// 滑块方向
        /// </summary>
        public SliderBlockOrientation Orientation
        {
            get { return (SliderBlockOrientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(SliderBlockOrientation), typeof(SliderBlock), new PropertyMetadata((SliderBlockOrientation.Both)));

        /// <summary>
        /// 滑块手柄
        /// </summary>
        public FrameworkElement Thumb
        {
            get { return (FrameworkElement)GetValue(ThumbProperty); }
            set { SetValue(ThumbProperty, value); }
        }

        public static readonly DependencyProperty ThumbProperty =
            DependencyProperty.Register("Thumb", typeof(FrameworkElement), typeof(SliderBlock), new PropertyMetadata(default(FrameworkElement)));
        /// <summary>
        /// 横坐标位置0-1
        /// </summary>
        public double X
        {
            get { return (double)GetValue(XProperty); }
            set { SetValue(XProperty, value); }
        }

        public static readonly DependencyProperty XProperty =
            DependencyProperty.Register("X", typeof(double), typeof(SliderBlock), new PropertyMetadata(0.5d));
        /// <summary>
        /// 纵坐标相对位置0-1
        /// </summary>
        public double Y
        {
            get { return (double)GetValue(YProperty); }
            set { SetValue(YProperty, value); }
        }

        public static readonly DependencyProperty YProperty =
            DependencyProperty.Register("Y", typeof(double), typeof(SliderBlock), new PropertyMetadata(0.5d));

        /// <summary>
        /// 用户操作导致的变化
        /// </summary>
        public event EventHandler DragChange;

        private void OnDragChange()
        {
            this.DragChange?.Invoke(this, EventArgs.Empty);
        }
    }
    /// <summary>
    /// 滑块方向
    /// </summary>
    public enum SliderBlockOrientation
    {
        X = 1,
        Y = 2,
        Both = 3
    }
    #endregion
}
